package com.yupi.springbootinit.statemachine.service;

import com.yupi.springbootinit.statemachine.core.StateContext;
import com.yupi.springbootinit.statemachine.core.TransitionResult;
import com.yupi.springbootinit.statemachine.enums.OrderStateEnum;
import com.yupi.springbootinit.statemachine.enums.ProcessInstanceStateEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;

/**
 * 状态自动推进服务
 * 监听状态变更事件，自动触发下一步状态转换和待办任务生成
 */
@Slf4j
@Service
public class AutoProgressService {
    
    @Autowired
    private StateMachineService stateMachineService;
    
    @Autowired
    private TaskCenterService taskCenterService;
    
    @Autowired
    private NotificationService notificationService;
    
    /**
     * 监听订单状态变更事件
     */
    @EventListener
    public void handleOrderStateChange(OrderStateChangeEvent event) {
        log.info("处理订单状态变更事件: 订单ID={}, 从状态={} 到状态={}", 
                event.getOrderId(), event.getFromState(), event.getToState());
        
        try {
            switch (event.getToState()) {
                case CREATED:
                    handleOrderCreated(event);
                    break;
                case ROUTING_PUBLISHED:
                    handleRoutingPublished(event);
                    break;
                case SCHEDULE_PUBLISHED:
                    handleSchedulePublished(event);
                    break;
                case PRODUCING:
                    handleOrderProducing(event);
                    break;
                case INSPECTING:
                    handleOrderInspecting(event);
                    break;
                case COMPLETED:
                    handleOrderCompleted(event);
                    break;
                default:
                    log.warn("未处理的订单状态: {}", event.getToState());
            }
        } catch (Exception e) {
            log.error("处理订单状态变更事件失败: 订单ID={}", event.getOrderId(), e);
        }
    }
    
    /**
     * 监听工序实例状态变更事件
     */
    @EventListener
    public void handleProcessInstanceStateChange(ProcessInstanceStateChangeEvent event) {
        log.info("处理工序实例状态变更事件: 工序ID={}, 从状态={} 到状态={}", 
                event.getProcessInstanceId(), event.getFromState(), event.getToState());
        
        try {
            switch (event.getToState()) {
                case IN_PROGRESS:
                    handleProcessStarted(event);
                    break;
                case PENDING_INSPECTION:
                    handleProcessPendingInspection(event);
                    break;
                case COMPLETED:
                    handleProcessCompleted(event);
                    break;
                case REJECTED:
                    handleProcessRejected(event);
                    break;
                default:
                    log.debug("工序状态变更: {}", event.getToState());
            }
            
            // 检查并更新订单整体状态
            updateOrderOverallState(event.getOrderId());
            
        } catch (Exception e) {
            log.error("处理工序实例状态变更事件失败: 工序ID={}", event.getProcessInstanceId(), e);
        }
    }
    
    /**
     * 处理订单创建事件
     */
    private void handleOrderCreated(OrderStateChangeEvent event) {
        // 生成工程部待办：创建工艺单
        taskCenterService.createTask(TaskCenterService.TaskType.CREATE_PROCESS_SHEET, 
                event.getOrderId(), "工程部", "创建工艺单");
        
        // 通知工程部
        notificationService.notifyDepartment("工程部", 
                String.format("新订单 %s 需要创建工艺单", event.getOrderId()));
        
        log.info("订单创建后续处理完成: 订单ID={}", event.getOrderId());
    }
    
    /**
     * 处理工艺发布事件
     */
    private void handleRoutingPublished(OrderStateChangeEvent event) {
        // 预生成检验任务模板给品质部
        taskCenterService.createInspectionTemplates(event.getOrderId());
        
        // 生成PMC待办：创建生产排期
        taskCenterService.createTask(TaskCenterService.TaskType.CREATE_PRODUCTION_SCHEDULE, 
                event.getOrderId(), "PMC", "创建生产排期");
        
        // 通知PMC
        notificationService.notifyDepartment("PMC", 
                String.format("订单 %s 工艺已发布，需要创建生产排期", event.getOrderId()));
        
        log.info("工艺发布后续处理完成: 订单ID={}", event.getOrderId());
    }
    
    /**
     * 处理排期发布事件
     */
    private void handleSchedulePublished(OrderStateChangeEvent event) {
        // 生成首道工序任务给生产部
        taskCenterService.createFirstProcessTask(event.getOrderId());
        
        // 通知生产部
        notificationService.notifyDepartment("生产部", 
                String.format("订单 %s 排期已发布，可以开始生产", event.getOrderId()));
        
        log.info("排期发布后续处理完成: 订单ID={}", event.getOrderId());
    }
    
    /**
     * 处理订单生产中事件
     */
    private void handleOrderProducing(OrderStateChangeEvent event) {
        // 通知项目部和管理员订单进入生产阶段
        notificationService.notifyMilestone(event.getOrderId(), "订单已进入生产阶段");
        
        log.info("订单生产中处理完成: 订单ID={}", event.getOrderId());
    }
    
    /**
     * 处理订单检验中事件
     */
    private void handleOrderInspecting(OrderStateChangeEvent event) {
        // 通知项目部和管理员订单进入检验阶段
        notificationService.notifyMilestone(event.getOrderId(), "订单已进入检验阶段");
        
        log.info("订单检验中处理完成: 订单ID={}", event.getOrderId());
    }
    
    /**
     * 处理订单完成事件
     */
    private void handleOrderCompleted(OrderStateChangeEvent event) {
        // 通知项目部和管理员订单完成
        notificationService.notifyMilestone(event.getOrderId(), "订单已完成");
        
        // 清理相关待办任务
        taskCenterService.cleanupOrderTasks(event.getOrderId());
        
        log.info("订单完成处理完成: 订单ID={}", event.getOrderId());
    }
    
    /**
     * 处理工序开始事件
     */
    private void handleProcessStarted(ProcessInstanceStateChangeEvent event) {
        // 记录工序开始时间
        // 实际应用中应该更新数据库记录
        log.info("工序开始: 工序ID={}, 订单ID={}", event.getProcessInstanceId(), event.getOrderId());
    }
    
    /**
     * 处理工序待检验事件
     */
    private void handleProcessPendingInspection(ProcessInstanceStateChangeEvent event) {
        // 生成品质部检验任务
        taskCenterService.createTask(TaskCenterService.TaskType.QUALITY_INSPECTION, 
                event.getProcessInstanceId(), "品质部", "工序检验");
        
        // 通知品质部
        notificationService.notifyDepartment("品质部", 
                String.format("工序 %s 需要检验", event.getProcessInstanceId()));
        
        log.info("工序待检验处理完成: 工序ID={}", event.getProcessInstanceId());
    }
    
    /**
     * 处理工序完成事件
     */
    private void handleProcessCompleted(ProcessInstanceStateChangeEvent event) {
        // 自动释放下一工序
        releaseNextProcess(event.getOrderId(), event.getProcessInstanceId());
        
        log.info("工序完成处理完成: 工序ID={}", event.getProcessInstanceId());
    }
    
    /**
     * 处理工序不合格事件
     */
    private void handleProcessRejected(ProcessInstanceStateChangeEvent event) {
        // 生成返工任务给生产部
        taskCenterService.createTask(TaskCenterService.TaskType.REWORK, 
                event.getProcessInstanceId(), "生产部", "返工/重做");
        
        // 通知生产部
        notificationService.notifyDepartment("生产部", 
                String.format("工序 %s 检验不合格，需要返工", event.getProcessInstanceId()));
        
        log.info("工序不合格处理完成: 工序ID={}", event.getProcessInstanceId());
    }
    
    /**
     * 释放下一工序
     */
    private void releaseNextProcess(Long orderId, Long currentProcessId) {
        // 查找下一道工序
        Long nextProcessId = findNextProcess(orderId, currentProcessId);
        if (nextProcessId != null) {
            // 生成下一工序任务
            taskCenterService.createTask(TaskCenterService.TaskType.PROCESS_EXECUTION, 
                    nextProcessId, "生产部", "工序执行");
            
            log.info("释放下一工序: 订单ID={}, 下一工序ID={}", orderId, nextProcessId);
        } else {
            // 检查是否所有工序都完成
            checkOrderCompletion(orderId);
        }
    }
    
    /**
     * 查找下一道工序
     */
    private Long findNextProcess(Long orderId, Long currentProcessId) {
        // 实际应用中应该查询数据库获取工序顺序
        // 这里返回模拟数据
        return null; // 简化实现
    }
    
    /**
     * 检查订单是否完成
     */
    private void checkOrderCompletion(Long orderId) {
        // 检查所有工序是否完成且检验合格
        boolean allProcessCompleted = checkAllProcessCompleted(orderId);
        boolean allInspectionPassed = checkAllInspectionPassed(orderId);
        
        if (allProcessCompleted && allInspectionPassed) {
            // 自动将订单状态更新为已完成
            StateContext context = new StateContext();
            context.setEntityId(orderId);
            context.setEntityType("ORDER");
            context.setCurrentState(OrderStateEnum.INSPECTING);
            context.setTargetState(OrderStateEnum.COMPLETED);
            
            TransitionResult result = stateMachineService.executeTransition(context);
            if (result.isSuccess()) {
                log.info("订单自动完成: 订单ID={}", orderId);
            } else {
                log.error("订单自动完成失败: 订单ID={}, 原因={}", orderId, result.getErrorMessage());
            }
        }
    }
    
    /**
     * 检查所有工序是否完成
     */
    private boolean checkAllProcessCompleted(Long orderId) {
        // 实际应用中应该查询数据库
        return true; // 简化实现
    }
    
    /**
     * 检查所有检验是否通过
     */
    private boolean checkAllInspectionPassed(Long orderId) {
        // 实际应用中应该查询数据库
        return true; // 简化实现
    }
    
    /**
     * 更新订单整体状态
     */
    private void updateOrderOverallState(Long orderId) {
        OrderStateEnum newState = calculateOrderOverallState(orderId);
        OrderStateEnum currentState = getCurrentOrderState(orderId);
        
        if (newState != currentState) {
            StateContext context = new StateContext();
            context.setEntityId(orderId);
            context.setEntityType("ORDER");
            context.setCurrentState(currentState);
            context.setTargetState(newState);
            
            TransitionResult result = stateMachineService.executeTransition(context);
            if (result.isSuccess()) {
                log.info("订单状态自动更新: 订单ID={}, 从 {} 到 {}", orderId, currentState, newState);
            } else {
                log.error("订单状态自动更新失败: 订单ID={}, 原因={}", orderId, result.getErrorMessage());
            }
        }
    }
    
    /**
     * 计算订单整体状态
     */
    private OrderStateEnum calculateOrderOverallState(Long orderId) {
        // 根据工序状态计算订单整体状态
        // 实际应用中应该查询数据库获取所有工序状态
        
        // 简化逻辑：
        // 1. 如果有工序在进行中/待检验/检验中 -> 生产中/检验中
        // 2. 如果所有工序完成且检验合格 -> 已完成
        
        return OrderStateEnum.PRODUCING; // 简化实现
    }
    
    /**
     * 获取当前订单状态
     */
    private OrderStateEnum getCurrentOrderState(Long orderId) {
        // 实际应用中应该查询数据库
        return OrderStateEnum.SCHEDULE_PUBLISHED; // 简化实现
    }
    
    /**
     * 订单状态变更事件
     */
    public static class OrderStateChangeEvent {
        private Long orderId;
        private OrderStateEnum fromState;
        private OrderStateEnum toState;
        private String operatorId;
        
        public OrderStateChangeEvent(Long orderId, OrderStateEnum fromState, OrderStateEnum toState, String operatorId) {
            this.orderId = orderId;
            this.fromState = fromState;
            this.toState = toState;
            this.operatorId = operatorId;
        }
        
        // Getters
        public Long getOrderId() { return orderId; }
        public OrderStateEnum getFromState() { return fromState; }
        public OrderStateEnum getToState() { return toState; }
        public String getOperatorId() { return operatorId; }
    }
    
    /**
     * 工序实例状态变更事件
     */
    public static class ProcessInstanceStateChangeEvent {
        private Long processInstanceId;
        private Long orderId;
        private ProcessInstanceStateEnum fromState;
        private ProcessInstanceStateEnum toState;
        private String operatorId;
        
        public ProcessInstanceStateChangeEvent(Long processInstanceId, Long orderId, 
                ProcessInstanceStateEnum fromState, ProcessInstanceStateEnum toState, String operatorId) {
            this.processInstanceId = processInstanceId;
            this.orderId = orderId;
            this.fromState = fromState;
            this.toState = toState;
            this.operatorId = operatorId;
        }
        
        // Getters
        public Long getProcessInstanceId() { return processInstanceId; }
        public Long getOrderId() { return orderId; }
        public ProcessInstanceStateEnum getFromState() { return fromState; }
        public ProcessInstanceStateEnum getToState() { return toState; }
        public String getOperatorId() { return operatorId; }
    }
}